package com.xbn.netty.simpleTcp;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @author XBN
 * @date 2020/10/19 10:30
 * @email 78742541@qq.com
 */
/*
* Netty服务器端
* */
public class NettyServer {
    public static void main(String[] args) throws InterruptedException {
        //创建BossGroup和WorkerGroup
        //创建两个线程组分别是bossGroup和workerGroup
        //bossGroup只处理连接请求，真正的和客户端业务处理 交给workerGroup完成
        //不管是bossGroup还是workerGroup他们都是无限循环监听的
        //BossGroup和workerGroup含有子线程(NioEventLoop)的个数默认是cpu的核心数*2
        //我们可以在参数中指定线程数量
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup(8);
        try {

            //创建服务器端启动的配置参数
            ServerBootstrap bootstrap = new ServerBootstrap();
            //使用链式编程来进行设置,设置两个线程组
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)//使用NioSocketChannel作为服务器通道实现
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE,true)  //设置保持连接活动状态
                    .childHandler(new ChannelInitializer<SocketChannel>() {//创建一个通道初始化对象(匿名对象)
                        //向pipeline设置处理器
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //往管道的最后增加一个处理器,NettyServerHandler是我们自己实现的一个自定义处理器
                            socketChannel.pipeline().addLast(new NettyServerHandler());
                        }
                    });//给worker Group的EventLoop 对应的管道设置处理器
            //绑定一个端口并且同步处理，生成一个channelFuture对象
            ChannelFuture channelFuture = bootstrap.bind(6668).sync();
            //监听绑定端口的情况，失败还是成功了
            channelFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if(channelFuture.isSuccess()) System.out.println("监听绑定端口成功");
                else System.out.println("监听绑定端口失败");
                }
            });
            //对关闭通道进行监听
            channelFuture.channel().closeFuture().sync();
        }finally {
            //优雅的关闭shutdownGracefully
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
